package com.hrg.rds.infra.executor.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.hrg.rds.biz.comm.NavService;
import com.hrg.rds.biz.config.RdsConfiguration;
import com.hrg.rds.biz.robot.domain.AgvVo;
import com.hrg.rds.biz.waybill.domain.instance.WaybillInstance;
import com.hrg.rds.biz.waybill.domain.instance.WaybillInstanceVo;
import com.hrg.rds.biz.waybill.domain.template.ParamType;
import com.hrg.rds.biz.waybill.domain.template.cmd.CmdParam;
import com.hrg.rds.biz.waybill.domain.template.cmd.CmdParamType;
import com.hrg.rds.biz.waybill.service.WaybillInstanceService;
import com.hrg.rds.infra.executor.CmdExecutor;
import com.hrg.rds.infra.executor.CmdInstanceContext;
import com.hrg.rds.infra.executor.CmdInstanceResult;
import com.hrg.sys.common.constant.UserConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service("SelectAgvCmd")
public class SelectAgvCmdExecutor implements CmdExecutor {
	private static final Map<String, AgvVo> AgvIpMap = RdsConfiguration.AgvIpMap;

	@Override
	public Duration getRetryInterval() {
		return Duration.ofSeconds(3);
	}

	@Override
	public CmdInstanceResult execute(List<CmdParam> params, CmdInstanceContext cmdInstanceContext) {
		log.info("SelectAgvCmdExecutor execute, cmdId = "+ cmdInstanceContext.getCmdId());
		try {
			Map<String, CmdParam> map = params.stream().collect(Collectors.toMap(CmdParam::getKey, Function.identity()));

			List<AgvVo> agvVoList = AgvIpMap.values().stream().filter(AgvVo::isIfAvailable).toList();
			if (CollUtil.isEmpty(agvVoList)) {
				log.info("No Available agvVoList");
				return CmdInstanceResult.retry();
			}


			if (map.containsKey("agvId")) {
				String agvId = map.get("agvId").getEvaluatedValue();
				log.info("agvId = {}", agvId);
				 if (StrUtil.isNotBlank(agvId) && AgvIpMap.containsKey(agvId)) {
					 // 找到车辆
					 agvVoList = agvVoList.stream().filter(agvVo -> agvVo.getId().equals(agvId)).toList();
					 if (CollUtil.isEmpty(agvVoList)) {
						 return CmdInstanceResult.retry();
					 }
				 }
			}

			/*if (map.containsKey("agvGroupId")) {
				String agvGroupId = map.get("agvGroupId").getEvaluatedValue();
				log.info("agvGroupId = {}", agvGroupId);
				if (StrUtil.isNotBlank(agvGroupId)) {
					agvVoList = agvVoList.stream().filter(agvVo -> agvVo.getGroupId().equals(agvGroupId)).toList();
					if (CollUtil.isEmpty(agvVoList)) {
						return CmdInstanceResult.retry();
					}
				}
			}*/
			if (map.containsKey("batteryLevel")) {
				boolean batteryLevel = map.get("batteryLevel").getBooleanEvaluatedValue();
				log.info("batteryLevel = {}", batteryLevel);
				if (batteryLevel) {
					agvVoList = agvVoList.stream().sorted(Comparator.comparingDouble(AgvVo::getBatteryLevel)).toList();
				}
			}
			// 关键站点则可以让系统在选择机器人时，选择距离“关键站点”较近的一辆 AGV
			if (map.containsKey("keyStation")) {
				String keyStation = map.get("keyStation").getEvaluatedValue();
				log.info("keyStation = {}", keyStation);
				if (StrUtil.isNotBlank(keyStation)) {
					agvVoList = agvVoList.stream().sorted(Comparator.comparingInt(agvVo -> NavService.getNavPathCnt(agvVo.getIp(), agvVo.getCurrentStation(), keyStation))).toList();
				}
			}

			Optional<AgvVo> first = agvVoList.stream().findFirst();
			if (first.isEmpty()) {
				return CmdInstanceResult.retry();
			}
			AgvVo agvVo = first.get();
			if (StrUtil.isNotBlank(agvVo.getWaybillInstanceId())) {
				CmdInstanceContext.setTerminated(agvVo.getWaybillInstanceId());
				return CmdInstanceResult.retry(Duration.ofSeconds(1), "终止自动任务中");
			}
			/*log.info("SelectAgvCmdExecutor execute success, waybillInstanceId = {}, agvId = {}, agvGroupId = {}, ip = {}, batteryLevel = {}, currentStation = {}",
					cmdInstanceContext.getWaybillInstanceId(), agvVo.getId(), agvVo.getGroupId(), agvVo.getIp(), agvVo.getBatteryLevel(), agvVo.getCurrentStation());*/
			log.info("SelectAgvCmdExecutor execute success, waybillInstanceId = {}, agvId = {}, ip = {}, batteryLevel = {}, currentStation = {}",
					cmdInstanceContext.getWaybillInstanceId(), agvVo.getId(), agvVo.getIp(), agvVo.getBatteryLevel(), agvVo.getCurrentStation());
			CmdParam cmdParam = CmdParam.builder().key("agvId").value(agvVo.getId()).cmdParamType(CmdParamType.Simple).required(true).paramType(ParamType.String).build();

			// 更新运单执行车辆
			WaybillInstance waybillInstance = new WaybillInstance();
			waybillInstance.setId(cmdInstanceContext.getWaybillInstanceId());
			waybillInstance.setAgvId(agvVo.getId());
			//waybillInstance.setAgvGroupId(agvVo.getGroupId());
			waybillInstance.setUpdateTime(new Date());
			waybillInstance.setUpdateBy(UserConstants.SYS_USER);
			SpringUtil.getBean(WaybillInstanceService.class).updateById(waybillInstance);
			// 更新运单执行车辆
			WaybillInstanceVo waybillInstanceVo = cmdInstanceContext.getWaybillInstanceVo();
			waybillInstanceVo.setAgvId(agvVo.getId());
			//waybillInstanceVo.setAgvGroupId(agvVo.getGroupId());

			return CmdInstanceResult.success().addCmdParams(cmdParam);

		} catch (Exception e) {
			log.error("SelectAgvCmdExecutor execute error", e);
			return CmdInstanceResult.retry(e.getMessage());
		}
	}
}
